package com.db.utils;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author dzh
 * @since 2025/1/3
 */
public class PdfImageUtils {

    // 将压缩包中pdf的发票内容提取出来，然后3张为一页，拼接为pdf，方便打印
    public static void main(String[] args) {
        String filePath = "C:/temp/abc.zip";
        File unzipPath = new File(filePath + "_unzip");
        File imageFile = new File(filePath + "_img");
        File mergeFile = new File(filePath + "_merge");
        // 解压
        File file = ZipUtil.unzip(new File(filePath), unzipPath);
        System.out.println(file.getAbsolutePath());

        // 转换为图片
        dealFiles(file, (f) -> {
            toImage(f.getAbsolutePath(), imageFile.getAbsolutePath() + "/" + f.getName() + ".png");
        });
        FileUtil.del(unzipPath);

        // 图片3张合并一张
        imageMerge(imageFile, mergeFile, 3);
        FileUtil.del(imageFile);

        imageToPdf(filePath + ".pdf", mergeFile);
        FileUtil.del(mergeFile);
    }

    public static void imageToPdf(String pdfPath, File imageBaseDir) {

        try (PDDocument document = new PDDocument()) {
            File[] files = imageBaseDir.listFiles();
            if (files == null) {
                return;
            }
            for (File file : files) {
                PDImageXObject pdImage = PDImageXObject.createFromFileByExtension(file, document);
                PDRectangle mediaBox = new PDRectangle(pdImage.getWidth(), pdImage.getHeight());
                PDPage page = new PDPage(mediaBox);
                document.addPage(page);
                PDPageContentStream contentStream = new PDPageContentStream(document, page);

                // 将图片绘制到PDF页面上
                contentStream.drawImage(pdImage, 0, 0);
                contentStream.close();
            }

            document.save(pdfPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void dealFiles(File file, Consumer<File> consumer) {
        if (file.isDirectory()) {
            for (File f : Objects.requireNonNull(file.listFiles())) {
                dealFiles(f, consumer);
            }
        } else {
            consumer.accept(file);
        }
    }

    public static void toImage(String pdfFilePath, String outputImagePath) {

        try (PDDocument document = PDDocument.load(new File(pdfFilePath))) {
            if (!document.isEncrypted()) {
                PDFRenderer pdfRenderer = new PDFRenderer(document);
                // 获取第一页的图片
                BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);

                // 保存图片
                File output = new File(outputImagePath);
                FileUtils.createParentDirectories(output);
                ImageIO.write(bufferedImage, "PNG", output);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void imageMerge(File dir, File mergeFile, int size) {
        File[] files = dir.listFiles();
        if (files == null) {
            return;
        }
        List<File> fileList = Arrays.stream(files).collect(Collectors.toList());
        imageMerge(fileList, mergeFile, size);
    }

    private static void imageMerge(List<File> files, File mergeFile, int size) {
        File baseFile = files.get(0).getParentFile();
        String basePath = baseFile.getAbsolutePath();
        files.sort((a, b) -> b.getName().compareTo(a.getName()));
        List<List<File>> partition = ListUtils.partition(files, size);
        String imageDic = mergeFile.getAbsolutePath() + "/";
        for (int i = 0; i < partition.size(); i++) {
            File imageFile = new File(imageDic + i + ".png");
            try {
                FileUtils.createParentDirectories(imageFile);
            } catch (Exception e) {
                // ignore
            }
            imageMerge(partition.get(i), imageFile.getAbsolutePath());
        }
    }

    private static void imageMerge(List<File> files, String target) {
        try {

            BufferedImage[] images = new BufferedImage[files.size()];
            for (int i = 0; i < files.size(); i++) {
                images[i] = ImageIO.read(files.get(i));
            }

            int width = images[0].getWidth();
            int height = Arrays.stream(images).mapToInt(BufferedImage::getHeight).sum();

            // 创建一个新的图片，宽度是两张图片的宽度之和，高度取最大值
            BufferedImage concatenatedImage = new BufferedImage(
                    width,
                    height,
                    BufferedImage.TYPE_INT_RGB);

            // 画图
            Graphics2D g2d = concatenatedImage.createGraphics();

            int startY = 0;
            for (BufferedImage image : images) {
                g2d.drawImage(image, 0, startY, null);
                startY += image.getHeight();
                g2d.drawLine(0, startY, image.getWidth(), startY += 3);
            }
            g2d.dispose();

            // 保存拼接后的图片
            File output = new File(target);
            FileUtils.createParentDirectories(output);
            ImageIO.write(concatenatedImage, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
